#ifndef MATRIX_H
#define MATRIX_H

#include <stdio.h>
#include <stdlib.h>

// 定义矩阵的两种类型
enum { MATRIX, SUB_MATRIX };

typedef struct {
  // 行数
  size_t row;

  // 列数
  size_t col;

  // 数组
  double *arr;

  // 矩阵类型，有矩阵`MATRIX`和子矩阵`SUB_MATRIX`两种类型
  int type;
} Matrix;

/**
 * 构造函数
 * 生成全零矩阵，主要是函数read_matrix使用
 * @param row, col 矩阵的行数、列数
 * @return 新生成的矩阵
 */
Matrix *make_zeros(size_t row, size_t col);

/**
 * 析构函数
 * 如果m的类型是矩阵，则释放空间并删除指针m
 * 如果是子矩阵，则只删除指针m
 */
void destroy_matrix(Matrix *m);

/**
 * 选择矩阵的一个元素
 * @param m 矩阵
 * @param i 元素所在行数
 * @param j 元素所在列数
 * @return 指向该元素的指针
 */
double *get_item(Matrix *m, size_t i, size_t j);

// I/O functions
/**
 * 按矩阵的格式输出矩阵到fp
 * 例如：
 *  1 2
 *  3 4
 * @param fp 输出的目标，FILE指针
 * @param m 输出的矩阵
 */
void display(FILE *fp, Matrix *m);

/**
 * 按题目要求的格式输出矩阵到fp
 * 例如：
 *  2 2
 *  1
 *  2
 *  3
 *  4
 * @param fp 输出的目标，FILE指针
 * @param m 输出的矩阵
 */
void write_matrix(FILE *fp, Matrix *m);

/**
 * 从文件读入一个矩阵，要求文件格式满足题目要求，
 * 主要由open_read_matrix调用
 * @param fp 待读入的矩阵所在的文件
 * @return 新建的矩阵
 */
Matrix *read_matrix(FILE *fp);

/**
 * 从给出的文件名读入矩阵
 * @param file_name 待读入矩阵的文件名
 * @return 由文件新建的矩阵
 */
Matrix *open_read_matrix(const char *file_name);

// sub-matrix
/**
 * 生成一个子矩阵
 * 子矩阵只是逻辑上的
 * @param src 原矩阵
 * @param lt 大小为2的size_t数组，表示子矩阵左上角元素的坐标
 * @param rb 大小为2的size_t数组，表示子矩阵右下角元素的坐标
 * @return 子矩阵的指针
 */
Matrix *get_sub(Matrix *src, size_t *lt, size_t *rb);

// dot
/**
 * 矩阵点乘
 * @param src1 矩阵1
 * @param src2 矩阵2
 * @param tar 存储结果的矩阵
 */ 
void dot(Matrix *src1, Matrix *src2, Matrix *tar);

#endif